Function Write-Log(){
	param(
		[Parameter(Mandatory=$true)]
		[ValidateSet("Warning", "Error", "Success","Normal")]
		$logType,
		[Parameter(Mandatory=$true)]
		$logInfo,
		[Parameter(Mandatory=$true)]
		$logfile
	)
	(get-date).tostring("yyyy-MM-dd HH:mm:ss")+"--"+$logType+": "+$logInfo |Out-File -FilePath $logfile -Append -Encoding utf8 -Force 
}
Function New-FileFolder($p,[Switch]$d){ # this function is used to create file/folder if it doesn't exist
  If(!(test-path $p -ErrorAction Ignore)){If($d){new-item -ItemType Directory -path $p -Force 1>$null}else{new-item -ItemType File -path $p -Force 1>$null}}
}
Function Set-FileAccess(){ # this function is used to add given user access to the given path
    param(
    	[Parameter(Mandatory=$True)]     
    	[string]$path,                   # the given path to add access
    	[Parameter(Mandatory=$True)]     
    	[string]$user,                   # the given user to be added access to the given path
    	[Parameter(Mandatory=$False)]    
    	[string]$access="Modify"         # the access type to be added, default is "Modify"
    )
	$Acl = (Get-Item $path).GetAccessControl('Access')
	$InheritanceFlags="None" ; $PropagationFlags="None"
	If( (Get-Item $path).psiscontainer){
	    $InheritanceFlags="ObjectInherit"
	}
	$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($user, $access,$InheritanceFlags, $PropagationFlags, 'Allow')
	$Acl.SetAccessRule($Ar)
	Set-Acl -path $path -AclObject $Acl
}
Function Send-Mailtoteam( ){ # this function is used to send email to notify team that the script finished.
	param(
		[Parameter(Mandatory=$True)]
		[string]$of_user,               # send by whom
		[Parameter(Mandatory=$True)]    
		[string]$taskRunResult,         # the result og script running: SUCCESS, FAILED, WARNING
		[Parameter(Mandatory=$false)]    
		[string]$NotSuccessInfo,        # the info in the subject to notify user what the not success info is
		[Parameter(Mandatory=$false)]    
		[string]$body_template,         # the massege to be replaced in email body for actual details
		[Parameter(Mandatory=$True)]     
		[string]$log,                   # the log file to be attached to send to the team
		[Parameter(Mandatory=$True)]     
		[string]$start_time             # the starttime of autosysjob
	)
	$this_pc=$env:computername
	$domain=((Get-WmiObject Win32_ComputerSystem).Domain.Split(".")[0]).ToUpper()
	$node=Switch -regex ($this_pc.Substring($this_pc.Length-2)){
	    "01|49|E2|9a"   {"1";break}
	    "02|b8|0e|ae"   {"2";break}
	    "03|72|27|50"   {"3"}
	}
	$env=Switch -regex ($this_pc.Substring(7,3).ToLower()){ # check computer name to tell the env
	    "p2n"           {"PROD";break}
	    "u2n"           {"UAT";break}
	    "-f2|-18|-aa"   {"DEV";break}
	    "-44|-97|-c2"   {"POC";break}
	    "-f3|-3d"       {"LAB";break}
	    "c2n"           {"COB";break}
	    "e2n"           {"PTE";break}
	    default         {$this_pc}
	}
	$env="[$env-$domain-$node]"
	$subject="$env RPA AA STE RDC Session Refresh - $taskRunResult$NotSuccessInfo"
	$run_mins=[Math]::Round(((get-date) - [datetime]$start_time).TotalMinutes)
	$body="Hi RPA AA STE Support, `n
$run_mins minutes have passed since the RDC session was restarted in $this_pc. `n
$body_template `n
Please check details in the attached log. `n
Thank You! `n
$of_user"
# cw50406@imcnam.ssmb.com  dl.gt.cn.cstc.rpa.aa.ste@imcnam.ssmb.com
    Try{
        Send-MailMessage `
            -From ($of_user+"."+$this_pc+"@imcnam.ssmb.com") `
            -To dl.gt.cn.cstc.rpa.aa.ste@imcnam.ssmb.com `
            -Subject $subject `
            -Body $body `
            -Attachments $log `
            -SmtpServer "imta.citicorp.com" -Port 25 `
            -Encoding([System.Text.Encoding]::UTF8) -ea 1
        Write-Log Success 'The notify email has been sent to RPA AA STE team.' $log
    }Catch{
        Write-Log Error $_ $log
    }Finally{}
}
Function Start-BulkThreads(){ # this function is used to run parallel threads so that is can save much time
    param(
    	[Parameter(Mandatory=$True)]
    	[Object[]]$vdilist,
    	[Parameter(Mandatory=$True)]
    	[ScriptBlock]$Action,
    	[Parameter(Mandatory=$false)]
    	[Object[]]$ActionParams,
    	[Parameter(Mandatory=$false)]
    	[int]$maxCnt=20
    )
	If( ($vdiCounts = $vdilist.Count) -eq 1 ){ # no need to create thread pool to run it
		If( [string]::IsNullOrWhiteSpace($vdilist[0]) ){
		    write-error "vdilist only contains 1 line but it's null"
		}else{& $Action $vdilist[0] 1 $ActionParams}
	}else{
		$throttleLimit=$maxCnt ; If($vdiCounts -le $maxCnt ){$throttleLimit=$vdiCounts}
		$SessionState = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
		$Pool = [runspacefactory]::CreateRunspacePool(1, $throttleLimit, $SessionState, $Host)
		$Pool.Open() ; $threads = @() ; $cnt=1
		$handles = foreach($line in $vdilist){
			$powershell = [powershell]::Create().AddScript($Action).AddArgument($line).AddArgument($cnt).AddArgument($ActionParams)
			$powershell.RunspacePool = $Pool ;	$powershell.BeginInvoke() ; $threads += $powershell ; $cnt++
		}
		do{
		  $i = 0 ;  $done = $true
		  foreach ($handle in $handles) {
			if($handle -ne $null){if($handle.IsCompleted){$threads[$i].EndInvoke($handle);$threads[$i].Dispose();$handles[$i]=$null}else{$done = $false}}
			$i++
		  }
		  if (-not $done) { Start-Sleep -Milliseconds 200 }
		} until ($done)
	}
}
Function Export-LogToAutosys( $log ){ # export powershell log to autosys logfile when it stoped
    Write-Log Normal "----------------END OF SCRIPT----------------`n" $log
	Try{
		get-content $log|Add-Content "C:\Program Files\CA\Workload Automation AE\SystemAgent\WA1_AGENT\log\RestartRDCSessions\out.log" -Force -Encoding UTF8
	}Catch{
	    write-log Error $_ $log
	}Finally{}
}
Function Stop-WithError(){ # this function is used when there is error with script running
    param(
    	[Parameter(Mandatory=$True)]
    	[string]$errorDetail,
    	[Parameter(Mandatory=$True)]
    	[string]$log,
    	[Parameter(Mandatory=$True)]
    	[string]$of_user,
    	[Parameter(Mandatory=$True)]
    	[string]$start_time
    )
    Write-Log Error $errorDetail $log
	Export-LogToAutosys $log
	$body_template="There is an error when running the RDC Session Refresh process`r`n`nError$errorDetail"
	Send-Mailtoteam $of_user "FAILED" $errorDetail $body_template $log $start_time
}